﻿#include "cmodbusclient.h"
#include "qmessagebox.h"
#include <QVariant>
#include <QDebug>
#include <QTime>
#include <QVector>

#include <iostream>

#define  SERVER_ID          1
using namespace std;
// 自定义的定时器
struct sModbusTimer
{
    QTime time;
    uint32_t interval;

    void start(uint32_t t)
    {
        interval = t;
        time.start();
    };

    bool isTimeOut()
    {
        return time.elapsed() > interval;
    };
};

CModbusClient::CModbusClient(QObject *parent) :
    QThread(parent)
    ,m_bConnected(false)
    ,m_bAppClose(false)
    ,m_connectionSuccessfulTimes(0)
    ,m_readTimes(0)
    ,m_readSuccessfulTimes(0)
    ,m_writeTimes(0)
    ,m_writeSuccessfulTimes(0)
    ,m_objectType(0)
    ,m_pClient(new QModbusTcpClient())
{
    //m_connectionSuccessfulTimes = 0;
    //m_readTimes = 0;
    //m_readSuccessfulTimes = 0;
    //m_writeTimes = 0;
    //m_writeSuccessfulTimes = 0;
    QObject::connect(this, &CModbusClient::signalConnectDevice, this, &CModbusClient::slotConnectDevice);
    QObject::connect(this, &CModbusClient::signalReadRegisterData, this, &CModbusClient::slotReadRegisterData);
    QObject::connect(this, &CModbusClient::signalWriteRegisterData, this, &CModbusClient::slotWriteRegisterData);
    QObject::connect(this, &CModbusClient::signalWriteFloatData, this, &CModbusClient::slotWriteFloatData);
    QObject::connect(this, &CModbusClient::signalWrite16RegisterData, this, &CModbusClient::slotWrite16RegisterData);
    QObject::connect(this, &CModbusClient::signalWrite32RegisterData, this, &CModbusClient::slotWrite32RegisterData);
    QObject::connect(m_pClient, &QModbusTcpClient::stateChanged, this, &CModbusClient::slotStateChanged);
    QObject::connect(m_pClient, &QModbusTcpClient::errorOccurred, this, &CModbusClient::slotErrorOccurred);

}

CModbusClient::~CModbusClient()
{
    m_bAppClose = true;

    std::cout << "~CModbusClient():" << m_bConnected << endl;

    //if (m_bConnected)
    {
        QThread::msleep(200);
        m_pClient->disconnect();
        m_bConnected = false;
    }
    delete m_pClient;
}

// connection
bool CModbusClient::connect(QString strIp, int nPort)
{
    if (m_bConnected)
        return true;
    m_pClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, QVariant::fromValue(nPort));
    m_pClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter,QVariant::fromValue(strIp));
    m_pClient->setTimeout(1000);
    m_pClient->setNumberOfRetries(3);
    m_pClient->connectDevice();
   // qDebug()<<m_pClient->connectionParameter();
    if (m_bConnected)
    {
        qDebug()<<"connected"<<strIp;
        m_connectionSuccessfulTimes++;
        m_readResponseAddrHoldingRegistersCoils.clear();
        emit signalUpdateState(1);
    }
    #ifndef QT_NO_DEBUG_OUTPUT
    else
        qDebug() << m_pClient->errorString() << "\n";
    #endif

    if (!this->isRunning())
        this->start();

    return m_bConnected;
}
//
bool CModbusClient::isConnected()
{
    return m_bConnected;
}

//资源释放
void  CModbusClient::release()
{
    m_bAppClose = true;
    // 延时确保后台线程全部退出
    QThread::msleep(200);
    m_pClient->disconnect();
    m_bConnected = false;
    //QThread::msleep(10);
    //delete m_pClient;
    //std::cout << "release:" << endl;
}
// 错误触发
void CModbusClient::slotErrorOccurred(QModbusDevice::Error error)
{
    #ifndef QT_NO_DEBUG_OUTPUT
    qDebug() << "ModbusClient Error Num:" << error << "\n";
    qDebug() << "ModbusClient Error Info:" << m_pClient->errorString() << "\n";
    #endif
    emit signalUpdateState(0);
}
// 连接状态变化
void CModbusClient::slotStateChanged(QModbusDevice::State state)
{
    switch (state)
    {
    case QModbusDevice::UnconnectedState:
    {
        m_bConnected = false;
        emit signalUpdateState(0);
    }break;
    case QModbusDevice::ConnectedState:
    {
        m_bConnected = true;
        emit signalUpdateState(1);
    }break;
    case QModbusDevice::ClosingState:
    {
        m_bConnected = false;
        emit signalUpdateState(0);
    }break;
    default:
        break;
    }
#ifndef QT_NO_DEBUG_OUTPUT
    qDebug() << "ModbusClient StateChanged:" << state << "\n";
#endif
}

void CModbusClient::disconnect()
{
    m_pClient->disconnectDevice();
}
//连接设备
void CModbusClient::slotConnectDevice()
{
    if (!m_bConnected)
    {
        m_readResponseAddrHoldingRegistersCoils.clear();
        m_pClient->connectDevice();
        if (m_bConnected)
        {
            if(m_connectionSuccessfulTimes == 0)
            {
                QObject::connect(m_pClient, &QModbusTcpClient::stateChanged, this, &CModbusClient::slotStateChanged);
                QObject::connect(m_pClient, &QModbusTcpClient::errorOccurred, this, &CModbusClient::slotErrorOccurred);
                m_connectionSuccessfulTimes++;
            }
        }
        #ifndef QT_NO_DEBUG_OUTPUT
        else
            qDebug() << m_pClient->errorString() << "\n";
        #endif
    }
}
//  返回读取的值
void CModbusClient::slotReadyRead()
{
    auto reply = qobject_cast<QModbusReply*>(sender());
    if (reply)
    {
        if (reply->error() == QModbusDevice::NoError)
        {
            const QModbusDataUnit unit = reply->result();
            uint16_t nStartAddr = unit.startAddress();

            auto valueList = unit.values();
            m_readSuccessfulTimes++;
            //将读取的返回值直接插入到值哈希表里面
            if (unit.registerType() == QModbusDataUnit::RegisterType::HoldingRegisters)
            {
                for (int i = 0; i < valueList.size(); i++)
                {
                    m_readValueHoldingRegistersHash[nStartAddr + i] = valueList[i];
                    //qDebug() << QString("Read HoldingRegisters Value[%1]:%2").arg(i + nStartAddr).arg(valueList[i]) << "\n";
                }
                #ifndef QT_NO_DEBUG_OUTPUT
                qDebug() << QString("Read HoldingRegisters Value[%1]:%2").arg(nStartAddr).arg(valueList.size()) << "\n";
                #endif
            }
            else if (unit.registerType() == QModbusDataUnit::RegisterType::Coils)
            {
                for (int i = 0; i < valueList.size(); i++)
                {
                    m_readValueCoilsHash[nStartAddr + i] = valueList[i];
                    //qDebug() << QString("Read Coils Value[%1]:%2").arg(i + nStartAddr).arg(valueList[i]) << "\n";
                }
                #ifndef QT_NO_DEBUG_OUTPUT
                qDebug() << QString("Read Coils Value[%1]:%2").arg(nStartAddr).arg(valueList.size()) << "\n";
                #endif
            }

        }
        #ifndef QT_NO_DEBUG_OUTPUT
        else
        {
            qDebug() << "ReadyRead Error:" << reply->errorString() << "\n";
        }
        #endif
        reply->deleteLater();
    }

}

// 后台线程
void CModbusClient::run()
{
    sModbusTimer timeout;
    int nStep = 0;
    int oneCycle = 0;
    int flagDisconnect = 0;
    while (true)
    {

        // 线程退出
        if (m_bAppClose)
            return;
        QThread::msleep(100);

        switch (nStep)
        {
        case 0:
        {
            if (!m_bConnected)
            {
                timeout.start(3 * 1000);
                nStep = 1;
                flagDisconnect = 1;
            }
            else
                nStep = 2;

        }break;

        case 1:
        {
            if (timeout.isTimeOut() && !m_bConnected)
            {
                // 通过发送信号，再次连接设备，不同线程需要用信号发送
                emit signalConnectDevice();
                nStep = 0;
            }
            else if (m_bConnected)
                nStep = 0;

        }break;

        case 2:
        {
            if(1 == flagDisconnect)
            {
                m_connectionSuccessfulTimes++;
                flagDisconnect = 0;
            }
            while(true && 0 == m_objectType)
            {
                int nReadIndex = 0;
                auto readkeys = m_readResponseAddrHoldingRegistersCoils.keys();
                auto keys_hold = m_readAddrHoldingRegistersHash.keys();
                auto keys_coil = m_readAddrCoilsHash.keys();

                for(nReadIndex = 0;nReadIndex < readkeys.size();nReadIndex++)
                {
                    uint16_t uAddr = readkeys[nReadIndex];
                    // 发送信号，读寄存器请求，不同线程需要用信号发送
                    if((QModbusDataUnit::RegisterType)m_readResponseAddrHoldingRegistersCoils[uAddr] == QModbusDataUnit::RegisterType::Coils)
                    {
                        for(int i = 0; i < keys_coil.size(); i++)
                        {
                            if(uAddr >= keys_coil[i] && uAddr < (keys_coil[i] + m_readAddrCoilsHash[keys_coil[i]]))
                            {
                                emit signalReadRegisterData(keys_coil[i], m_readAddrCoilsHash[keys_coil[i]], (int)QModbusDataUnit::RegisterType::Coils);
                                break;
                            }
                        }
                    }
                    else
                    {
                        for(int i = 0; i < keys_hold.size(); i++)
                        {
                            if(uAddr >= keys_hold[i] && uAddr < (keys_hold[i] + m_readAddrHoldingRegistersHash[keys_hold[i]]))
                            {
                                emit signalReadRegisterData(keys_hold[i], m_readAddrHoldingRegistersHash[keys_hold[i]], (int)QModbusDataUnit::RegisterType::HoldingRegisters);
                                break;
                            }
                        }
                    }
                    QThread::msleep(50);
                }
                m_readResponseAddrHoldingRegistersCoils.clear();
                QThread::msleep(50);
                break;
            }
            if (m_bAppClose)
                return;

            // 后台不断刷新读取
            if(1 == m_objectType)
            {
                auto keys = m_readAddrHoldingRegistersHash.keys();
                uint16_t uAddr = keys[0];
                if(flagDisconnect == 0)
                    std::cout << "uAddr:" << uAddr << " m_readAddrHoldingRegistersHash[uAddr]" <<  m_readAddrHoldingRegistersHash[uAddr] << "keys.size()" << keys.size() << endl;
                flagDisconnect = 2;


                    // 发送信号，读寄存器请求，不同线程需要用信号发送
                emit signalReadRegisterData(uAddr, m_readAddrHoldingRegistersHash[uAddr],(int)QModbusDataUnit::RegisterType::HoldingRegisters);
                m_readTimes++;
                QThread::msleep(100);
            }
            else if (true)
            {
                static int nIndex_hold = 0;
                auto keys = m_readAddrHoldingRegistersHash.keys();
                if(1 == m_objectType)
                    std::cout << "nIndex_hold:" << nIndex_hold << "keys.size()" << keys.size() << endl;
                if (nIndex_hold < keys.size())
                {
                    uint16_t uAddr = keys[nIndex_hold];

                    // 发送信号，读寄存器请求，不同线程需要用信号发送
                    emit signalReadRegisterData(uAddr, m_readAddrHoldingRegistersHash[uAddr],(int)QModbusDataUnit::RegisterType::HoldingRegisters);
                    m_readTimes++;
                    nIndex_hold++;
                }
                else
                {
                    nIndex_hold = 0;
                    oneCycle |= 1;
                }
            }
            if (m_bAppClose)
                return;
            QThread::msleep(100);
            if (true && 0 == m_objectType)
            {
                static int nIndex_coil = 0;
                auto keys = m_readAddrCoilsHash.keys();

                if (nIndex_coil < keys.size())
                {
                    uint16_t uAddr = keys[nIndex_coil];

                    // 发送信号，读寄存器请求，不同线程需要用信号发送
                    emit signalReadRegisterData(uAddr, m_readAddrCoilsHash[uAddr], (int)QModbusDataUnit::RegisterType::Coils);
                    m_readTimes++;
                    nIndex_coil++;
                }
                else
                {
                    nIndex_coil = 0;
                    oneCycle |= 2;
                    if(oneCycle == 3)
                    {
                        emit signalUpdateDevice();
                        oneCycle = 0;
                        #ifndef QT_NO_DEBUG_OUTPUT
                        qDebug() << "Connection quality:" << m_connectionSuccessfulTimes << "," << m_readTimes << "," << m_readSuccessfulTimes << "," << m_writeTimes << "," << m_writeSuccessfulTimes << "\n";
                        #endif
                    }
                }
            }
            else {
                QThread::msleep(10);
            }

            if (!m_bConnected)
                nStep = 0;
        }break;

        default:
            break;
        }
    }

}

// 发送寄存器读取请求
void CModbusClient::slotReadRegisterData(int nStartAddress, int nNum, int  type)
{
    QModbusDataUnit readUnit((QModbusDataUnit::RegisterType)type, nStartAddress, nNum);
    if (auto* reply = m_pClient->sendReadRequest(readUnit, SERVER_ID))
    {
        if (!reply->isFinished())
            QObject::connect(reply, &QModbusReply::finished, this, &CModbusClient::slotReadyRead);
        else
            delete reply;
    }
    #ifndef QT_NO_DEBUG_OUTPUT
    else
        qDebug() << m_pClient->errorString();
    #endif
}

// 发送寄存器写入请求
void CModbusClient::slotWriteRegisterData(int nStartAddress, uint16_t uValue, int type)
{
    if (!m_bConnected)
        return;

    const int nLength = 1;
    QModbusDataUnit writeUnit((QModbusDataUnit::RegisterType)type, nStartAddress, nLength);
    writeUnit.setValue(0, uValue);

    auto *reply = m_pClient->sendWriteRequest(writeUnit, SERVER_ID);
    if (reply != nullptr)
    {
        if (!reply->isFinished())
        {
            QObject::connect(reply, &QModbusReply::finished, this, [this, reply]()
            {
                if (reply->error() != QModbusDevice::NoError)
                {
                    #ifndef QT_NO_DEBUG_OUTPUT
                    qDebug() << "write response error:" << reply->errorString();
                    #endif
                }
                else
                {
                    m_writeSuccessfulTimes++;
                }
                reply->deleteLater();
            });
        }
        else
        {
            if (reply->error() == QModbusDevice::NoError)
                m_writeSuccessfulTimes++;
            reply->deleteLater();
        }
        m_readResponseAddrHoldingRegistersCoils[nStartAddress] = type;
    }
    #ifndef QT_NO_DEBUG_OUTPUT
    else
        qDebug() << "write request error:" << m_pClient->errorString();
    #endif

}
void CModbusClient::slotWrite16RegisterData(int nStartAddress, QVector<uint16_t> &uValue, int lens, int type)
{
    if (!m_bConnected)
        return;

    const int nLength = lens;
    QModbusDataUnit writeUnit((QModbusDataUnit::RegisterType)type, nStartAddress, nLength);
    for(int i = 0; i < lens; i++)
    {
        writeUnit.setValue(i, uValue[i]);
    }
    //std::cout << "slotWrite16RegisterData:m_writeSuccessfulTimes:" << m_writeSuccessfulTimes << endl;
    auto *reply = m_pClient->sendWriteRequest(writeUnit, SERVER_ID);
    if (reply != nullptr)
    {
        if (!reply->isFinished())
        {
            QObject::connect(reply, &QModbusReply::finished, this, [this, reply]()
            {
                if (reply->error() != QModbusDevice::NoError)
                {
                    #ifndef QT_NO_DEBUG_OUTPUT
                    qDebug() << "write response error:" << reply->errorString();
                    #endif
                }
                else
                    m_writeSuccessfulTimes++;
                reply->deleteLater();
            });
        }
        else
        {
            if (reply->error() == QModbusDevice::NoError)
                m_writeSuccessfulTimes++;
            reply->deleteLater();
        }
        m_readResponseAddrHoldingRegistersCoils[nStartAddress] = type;
        //std::cout << "slotWrite16RegisterData:nStartAddress:" << nStartAddress << ":m_writeSuccessfulTimes:" << m_writeSuccessfulTimes << endl;
    }
    #ifndef QT_NO_DEBUG_OUTPUT
    else
        qDebug() << "write request error:" << m_pClient->errorString();
    #endif

}
void CModbusClient::slotWrite32RegisterData(int nStartAddress, QVector<uint32_t> &uValue, int lens, int type)
{
    uint16_t uData16[2] = {0};

    if (!m_bConnected)
        return;

    const int nLength = lens*2;
    QModbusDataUnit writeUnit((QModbusDataUnit::RegisterType)type, nStartAddress, nLength);
    for(int i = 0; i < lens; i++)
    {
        uData16[0] = uValue[i] & 0Xffff;
        uData16[1] = (uValue[i] >> 16) & 0Xffff;
        writeUnit.setValue(i*2, uData16[0]);
        writeUnit.setValue(i*2+1, uData16[1]);
    }

    auto *reply = m_pClient->sendWriteRequest(writeUnit, SERVER_ID);
    if (reply != nullptr)
    {
        if (!reply->isFinished())
        {
            QObject::connect(reply, &QModbusReply::finished, this, [this, reply]()
            {
                if (reply->error() != QModbusDevice::NoError)
                {
                    #ifndef QT_NO_DEBUG_OUTPUT
                    qDebug() << "write response error:" << reply->errorString();
                    #endif
                }
                else
                    m_writeSuccessfulTimes++;
                reply->deleteLater();
            });
        }
        else
        {
            if (reply->error() == QModbusDevice::NoError)
                m_writeSuccessfulTimes++;
            reply->deleteLater();
        }
        m_readResponseAddrHoldingRegistersCoils[nStartAddress] = type;
    }
    else
        qDebug() << "write request error:" << m_pClient->errorString();

}
void CModbusClient::slotWriteFloatData(int nStartAddress, QVector<float> &uValue, int lens, int type)
{
    union change
    {
       float d;
       unsigned int m;
    }r1;
    uint16_t uData16[2] = {0};

    if (!m_bConnected)
        return;

    const int nLength = lens*2;
    QModbusDataUnit writeUnit((QModbusDataUnit::RegisterType)type, nStartAddress, nLength);
    for(int i = 0; i < lens; i++)
    {
        r1.d = uValue[i];
        uData16[0] = r1.m & 0Xffff;
        uData16[1] = (r1.m >> 16) & 0Xffff;
        writeUnit.setValue(i*2, uData16[0]);
        writeUnit.setValue(i*2+1, uData16[1]);
    }

    auto *reply = m_pClient->sendWriteRequest(writeUnit, SERVER_ID);
    if (reply != nullptr)
    {
        if (!reply->isFinished())
        {
            QObject::connect(reply, &QModbusReply::finished, this, [this, reply]()
            {
                if (reply->error() != QModbusDevice::NoError)
                {
                    #ifndef QT_NO_DEBUG_OUTPUT
                    qDebug() << "write response error:" << reply->errorString();
                    #endif
                }
                else
                    m_writeSuccessfulTimes++;
                reply->deleteLater();
            });
        }
        else
        {
            if (reply->error() == QModbusDevice::NoError)
                m_writeSuccessfulTimes++;
            reply->deleteLater();
        }
        m_readResponseAddrHoldingRegistersCoils[nStartAddress] = type;
    }
    #ifndef QT_NO_DEBUG_OUTPUT
    else
        qDebug() << "write request error:" << m_pClient->errorString();
    #endif

}
// 写入16位值
bool CModbusClient::readRegister16(uint16_t uAddr, uint16_t &uValue)
{
    if (!m_bConnected)
        return false;

    // 一次设置读取长度为100
    const int nReadLength = 100;

    // 如果值读取哈希链表没有找到，需要插入到地址哈希链表，让它在后台读取
    auto itFind = m_readValueHoldingRegistersHash.find(uAddr);
    if (itFind == m_readValueHoldingRegistersHash.end())
    {
        //m_readAddrHoldingRegistersHash[uAddr] = nReadLength;
        return false;
    }
    else
    {
        // 找到值，直接返回
        uValue = m_readValueHoldingRegistersHash[uAddr];
    }

    return true;
}

// 读取32位值
bool CModbusClient::readRegister32(uint32_t uAddr, uint32_t &uValue)
{
    if (!m_bConnected)
        return false;

    bool bRet = false;
    uint16_t uData16[2] = { 0 };
    bRet = readRegister16(uAddr, uData16[0]);
    if(bRet == true)
        bRet = readRegister16(uAddr + 1, uData16[1]);

    uValue = uData16[0]  | (uData16[1] << 16);

    return bRet;
}
bool CModbusClient::readFloat32(uint32_t uAddr, float &uValue)
{
    union change
    {
       float d;
       unsigned int m;
    }r1;

    if (!m_bConnected)
        return false;

    bool bRet = false;
    uint16_t uData16[2] = { 0 };
    bRet = readRegister16(uAddr, uData16[0]);
    if(bRet == true)
        bRet = readRegister16(uAddr + 1, uData16[1]);

    r1.m = uData16[0]  | (uData16[1] << 16);
    uValue = r1.d;
    return bRet;
}

// 获取位值
bool CModbusClient::getBit(uint16_t uAddr, uint16_t uBit)
{
    if (!m_bConnected)
        return false;

    uint16_t uValue = 0;
    readRegister16(uAddr, uValue);

    return uValue & (1 << (uBit % 16));
}

// 读取线圈值
bool CModbusClient::readCoil(uint16_t uAddr, uint16_t &uValue)
{
    //qDebug()<<"notfind"<<uAddr;
    const int nReadLength = 100;
    auto itFind = m_readValueCoilsHash.find(uAddr);
    if (itFind == m_readValueCoilsHash.end())
    {
        //m_readAddrCoilsHash[uAddr] = nReadLength;
        return false;
    }
    else
        uValue = m_readValueCoilsHash[uAddr];

    return true;
}

// 设置位值
bool CModbusClient::setBit(uint16_t uAddr, uint16_t uBit, bool bState)
{
    bool bRet = false;

    uint16_t uValue = 0;
    bRet = readRegister16(uAddr, uValue);

    if (bRet)
    {
        if (bState)
            uValue |= (1 << (uBit % 16));	 // 把某位置1
        else
            uValue &= ~(1 << (uBit % 16));	 // 把某位置0

        writeRegister16(uAddr, uValue);
    }

    return bRet;
}

// 写入16位值
bool CModbusClient::writeRegister16(uint16_t uAddr, uint16_t uValue)
{
    bool bRet = true;
    signalWriteRegisterData(uAddr, uValue, (int)QModbusDataUnit::RegisterType::HoldingRegisters);
    return bRet;
}

// 写入32位值
bool CModbusClient::writeRegister32(uint32_t uAddr, uint32_t uValue)
{
    bool bRet = false;

    uint16_t uData16[2] = {0};
    uData16[0] = uValue & 0Xffff;
    uData16[1] = (uValue >> 16) & 0Xffff;

    bRet = writeRegister16(uAddr, uData16[0]);
    bRet = writeRegister16(uAddr+1, uData16[1]);

    return bRet;
}

// 写入线圈值
bool CModbusClient::writeCoil(uint16_t uAddr, uint16_t uValue)
{
    bool bRet = true;
    emit signalWriteRegisterData(uAddr, uValue, (int)QModbusDataUnit::RegisterType::Coils);
    m_writeTimes++;
    return bRet;
}
bool CModbusClient::writeRegister16Vector(uint16_t uAddr, QVector<uint16_t> &uValue, int lens)
{
    bool bRet = true;
    emit signalWrite16RegisterData(uAddr, uValue, lens, (int)QModbusDataUnit::RegisterType::HoldingRegisters);
    m_writeTimes++;
    return bRet;
}
bool CModbusClient::writeRegister32Vector(uint32_t uAddr, QVector<uint32_t> &uValue, int lens)
{
    bool bRet = true;
    emit signalWrite32RegisterData(uAddr, uValue, lens, (int)QModbusDataUnit::RegisterType::HoldingRegisters);
    m_writeTimes++;
    return bRet;
}
bool CModbusClient::writeRegisterFloatVector(uint32_t uAddr, QVector<float> &uValue, int lens)
{
    bool bRet = true;
    emit signalWriteFloatData(uAddr, uValue, lens, (int)QModbusDataUnit::RegisterType::HoldingRegisters);
    m_writeTimes++;
    return bRet;
}
bool CModbusClient::writeCoilVector(uint16_t uAddr, QVector<uint16_t> &uValue, int lens)
{
    bool bRet = true;
    emit signalWrite16RegisterData(uAddr, uValue, lens, (int)QModbusDataUnit::RegisterType::Coils);
    m_writeTimes++;
    return bRet;
}

bool CModbusClient::initReadRegister16(uint32_t uAddr, uint32_t lens)
{
    m_readAddrHoldingRegistersHash[uAddr] = lens;
    return true;
}
bool CModbusClient::initReadCoil(uint32_t uAddr, uint32_t lens)
{
    m_readAddrCoilsHash[uAddr] = lens;
    return true;
}
void CModbusClient::emitReadCoil(uint16_t uAddr, int lens)
{
    emit signalReadRegisterData(uAddr, lens, (int)QModbusDataUnit::RegisterType::Coils);
}
void CModbusClient::emitReadHoldRegisters(uint16_t uAddr, int lens)
{
    emit signalReadRegisterData(uAddr, lens, (int)QModbusDataUnit::RegisterType::HoldingRegisters);
}
void CModbusClient::printReadHoldRegisters(int &a1,int &a2)
{

    auto keys_hold = m_readAddrHoldingRegistersHash.keys();
    auto keys_coil = m_readAddrCoilsHash.keys();
    a1 = keys_hold.size();
    a2 = keys_coil.size();
#if 0
    qDebug() << "size" << keys_hold.size() << keys_coil.size() << "\n";
    for(int i=0;i<keys_hold.size();i++)
    {
        qDebug() << QString("m_readAddrHoldingRegistersHash[%1]:%2").arg(keys_hold[i]).arg(m_readAddrHoldingRegistersHash[keys_hold[i]]).toStdString() << "\n";
    }
    for(int i=0;i<keys_coil.size();i++)
    {
        qDebug() << QString("m_readAddrCoilsHash[%1]:%2").arg(keys_coil[i]).arg(m_readAddrCoilsHash[keys_coil[i]]).toStdString() << "\n";
    }
#endif
}
